糖果
Time Limit: 10 Sec Memory Limit: 128 MB
Description
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入的第一行是两个整数N,K。
接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。
如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;
如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;
如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;
如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;
如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;
Output
输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
Sample Output
11
HINT
对于30%的数据,保证 N<=100
对于100%的数据,保证 N<=100000
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N
Main idea
有若干个小朋友分糖果,要求每个人至少分到一颗糖,给出若干个数之间大小或者等于的限制,求最少需要多少个糖果可以满足条件。
Solution
发现有若干限制大小,那么我们想到了差分约束系统,在两点之间连一条带权边,根据限制条件决定边权 。因为要满足所有情况,我们先将所有点入队,跑一遍最长路 即可求出答案。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 #include <bits/stdc++.h> using namespace std;const int ONE=200001 ;const int INF=2147483640 ;int n,m;int PD,x,y;int next[ONE],first[ONE],go[ONE],tot;int w[ONE];int dist[100001 ];int vis[100001 ],q[1000001 ],tou,wei;long long Ans;int Take_ring[100001 ];int get () { int res,Q=1 ; char c; while ( (c=getchar ())<48 || c>57 ) if (c=='-' )Q=-1 ; if (Q) res=c-48 ; while ((c=getchar ())>=48 && c<=57 ) res=res*10 +c-48 ; return res*Q; } int Add (int u,int v,int z) { next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z; } void PD_same (int x,int y) { if (x==y) { printf ("-1" ); exit (0 ); } } int Spfa () { while (tou<wei) { int u=q[++tou]; for (int e=first[u];e;e=next[e]) { int v=go[e]; if (dist[v]<dist[u]+w[e]) { if (++Take_ring[v]>=n) return 0 ; dist[v]=dist[u]+w[e]; if (!vis[v]) { vis[v]=1 ; q[++wei]=v; } } } vis[u]=0 ; } return 1 ; } int main () { n=get (); m=get (); for (int i=1 ;i<=m;i++) { PD=get (); x=get (); y=get (); if (PD==1 ) Add (x,y,0 ),Add (y,x,0 ); if (PD==2 ) Add (x,y,1 ),PD_same (x,y); if (PD==3 ) Add (y,x,0 ); if (PD==4 ) Add (y,x,1 ),PD_same (x,y); if (PD==5 ) Add (x,y,0 ); } for (int i=1 ;i<=n;i++) { dist[i]=vis[i]=1 ; q[++wei]=i; } if (!Spfa ()) { printf ("-1" ); return 0 ; } for (int i=1 ;i<=n;i++) Ans+=(long long )dist[i]; printf ("%lld" ,Ans); }